import { at, isArray, isString } from 'lodash-es'
import dayjs from 'dayjs'

/**
 * @ClassName DataFormat
 * @Description 数据格式化
 * @Author xuyizhuo
 * @Date 2024/12/15 18:43
 */
export default class DataFormat {
    /** 数据为空时的默认值 */
    static readonly DEFAULT_VALUE = '-' // 默认值

    /** 日期格式：精确到分钟 */
    static readonly DATE_FORMAT = 'YYYY-MM-DD'

    /** 时间格式：精确到分钟 */
    static readonly DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm'

    /** 时间格式：精确到毫秒数 */
    static readonly DATE_TIME_FULL_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS'

    /**
     * 获取一个默认值，如果值为空，则返回默认值
     * @param value 值
     * @param {any} defaultValue 默认值
     * @returns {any}
     */
    static getDefaultValue(value: any, defaultValue = this.DEFAULT_VALUE) {
        if ((!value && value !== 0) || (isArray(value) && value?.length < 1) || value === 'Invalid Date') {
            return defaultValue
        }
        return value
    }

    /**
     * 获取一个对象某个属性的默认值
     * @param obj 对象
     * @param key 需要获取值的属性，支持lodash的at行数写法。参考：https://www.lodashjs.com/docs/lodash.at/
     * @param defaultValue 默认值
     * @returns {any}
     * @example
     *      const object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
     *      DataFormat.getObjectDefaultValue(object, 'a[0].b.c') // 3
     */
    static getObjectDefaultValue(obj: AnyObject, key: string, defaultValue = this.DEFAULT_VALUE) {
        return this.getDefaultValue(at(obj, key)?.[0], defaultValue)
    }

    /**
     * 时间数据格式化
     * @param {string} time 时间
     * @param {string} format 时间的格式
     * @param defaultValue 默认值
     */
    static timeFormat(
        time: string | number | Date | dayjs.Dayjs | null | undefined,
        format = this.DATE_TIME_FORMAT,
        defaultValue = this.DEFAULT_VALUE,
    ) {
        if (!time || (isString(time) && time?.trim().length < 1)) {
            return defaultValue
        }
        return dayjs(time).format(format)
    }

    /**
     * 千分符
     * @param {string} num
     * @param {string} format
     * @returns {string}
     */
    static numGroupSeparator(num: number | string) {
        num = String(num)
        if (!num.includes('.')) num += '.'

        return num
            .replace(/(\d)(?=(\d{3})+\.)/g, ($0, $1) => {
                return `${$1},`
            })
            .replace(/\.$/, '')
    }

    /**
     * 将数字取整为10的倍数，如将 2345 可以处理为 2300 | 2400 | 3000 | 2000
     * @param num 需要取整的值
     * @param prec 需要用0占位的数量，默认（负数）为取长度-1
     * @param ceil 是否向上取整
     * @returns {number}
     */
    static formatRoundNum(num: number, prec = -1, ceil = true) {
        if (num < 10) {
            return 10
        }
        if (prec <= 0) {
            prec = String(num).length - 1
        }

        const mult = 10 ** prec
        return ceil ? Math.ceil(num / mult) * mult : Math.floor(num / mult) * mult
    }

    /**
     * 字符串长度补全。默认处理数字的位数补全，不足位数填充0。比如 1 => 01
     * @param {number} num
     * @param bit 补充0的位数，默认为2，如果小于或等于0，则不填充
     * @param padStr 补足的字符，默认为0
     * @returns {string}
     */
    static dataPadStart(num: number | string, bit = 2, padStr = '0') {
        if (!num) {
            return ''
        }
        if (bit <= 0) {
            return num
        }
        return String(num).padStart(bit, padStr)
    }
}
